package cc.shacocloud.mirage.restful.cors;

import cc.shacocloud.mirage.restful.Filter;
import cc.shacocloud.mirage.restful.HttpRequest;
import cc.shacocloud.mirage.restful.HttpResponse;
import cc.shacocloud.mirage.restful.RoutingContext;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpMethod;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * cors 过滤器
 */
@Slf4j
public class CorsFilter implements CorsProcessor, Filter {
    
    private final CorsConfiguration corsConfiguration;
    
    private final CorsProcessor corsProcessor;
    
    public CorsFilter(CorsConfiguration corsConfiguration) {
        this.corsConfiguration = corsConfiguration;
        this.corsProcessor = new DefaultCorsProcessor();
    }
    
    public CorsFilter(CorsConfiguration corsConfiguration, CorsProcessor corsProcessor) {
        this.corsConfiguration = corsConfiguration;
        this.corsProcessor = corsProcessor;
    }
    
    @Override
    public void doFilter(@NotNull RoutingContext context, @NotNull Promise<RoutingContext> doFilterFuture) {
        final HttpRequest request = context.request();
        final HttpResponse response = context.response();
        processRequest(corsConfiguration, request, response).onComplete(ar -> {
            if (ar.succeeded()) {
                
                // 如果是 OPTIONS 请求直接结束
                if (HttpMethod.OPTIONS.equals(request.method())) {
                    response.end();
                    doFilterFuture.complete();
                    return;
                }
                
                doFilterFuture.complete(context);
                return;
            }
            
            if (log.isWarnEnabled()) log.warn("", ar.cause());
            response.setStatusCode(HttpResponseStatus.INTERNAL_SERVER_ERROR.code());
            response.end();
            doFilterFuture.complete();
        });
    }
    
    @Override
    public Future<Boolean> processRequest(@Nullable CorsConfiguration configuration, HttpRequest request, HttpResponse response) {
        return corsProcessor.processRequest(configuration, request, response);
    }
}
